package javablackbelt.beans.factory.config;

import java.lang.reflect.Field;
import java.util.List;

import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionVisitor;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringValueResolver;

public class BeanDefinitionEncodedPropertyVisitor extends BeanDefinitionVisitor {

	private Base64PropertyDecoderSupport decoderSupport;

	public BeanDefinitionEncodedPropertyVisitor(Base64PropertyDecoderSupport decoderSupport, 
												StringValueResolver resolver) {
		super(resolver);
		this.decoderSupport = decoderSupport;
	}
	/**
	 * Traverse the given BeanDefinition object and the MutablePropertyValues
	 * and ConstructorArgumentValues contained in them.
	 * @param beanDefinition the BeanDefinition object to traverse
	 * @see #resolveStringValue(String)
	 */
	public void visitBeanDefinition(BeanDefinition beanDefinition) {
		visitPropertyValues(beanDefinition);
	}
	
	protected void visitPropertyValues(BeanDefinition bd) {
		Class<?> beanClass = null;
		
		try {
			beanClass = Class.forName(bd.getBeanClassName());
			// TODO: Handle the case where the class is define in a parent definition
		}
		catch (ClassNotFoundException e) {
		}
		
		List<Field> encodedFiels = this.decoderSupport.findEncodedFields(beanClass);
		
		if (encodedFiels != null) {
			
			for (Field field : encodedFiels) {
				
				PropertyValue[] pvArray = bd.getPropertyValues().getPropertyValues();
				
				for (int i = 0; i < pvArray.length; i++) {
					PropertyValue pv = pvArray[i];
					
					if (field.getName().equals(pv.getName())) {
						Object newVal = resolveValue(pv.getValue());
						if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {
							bd.getPropertyValues().addPropertyValue(pv.getName(), newVal);
						}
						
					}
				}
				
			}
		}
		
	}
}
